home *** CD-ROM | disk | FTP | other *** search
/ Aminet 4 / Aminet 4 - November 1994.iso / aminet / comm / ums / listclient3_1.lha / ListClient.rexx next >
OS/2 REXX Batch file  |  1994-09-26  |  11KB  |  365 lines

  1. /* ------------------------------------------------------------------------
  2. :Program.    ListClient 3.0
  3. :Contents.   transfers mail from a mailing list to a group and vice versa
  4. :Author.     Kai Bolay [kai]
  5. :Address.    Snail Mail:              EMail:
  6. :Address.    Hoffmannstraße 168       UUCP: kai@amokle.stgt.sub.org
  7. :Address.    D-71229 Leonberg         FIDO: 2:2407/106.3
  8. :History.    v1.0 [kai] 23-Sep-93
  9. :History.    v1.0 [kai] 14-Nov-93 added MakeFlags()
  10. :History.    v2.0 [kai]  3-Dec-93 removed links, added "oid<>"-support
  11. :History.    v2.1 [kai]  3-Dec-93 only move local msgs from group to ml
  12. :History.    v3.0 [hG ] 07 Aug 94 argument parsing, new command line syntax,
  13.                                   default login name and passwd, config var,
  14.                                   uses UMSInitStem,  "Mailinglist 'foo'",
  15.                                   auto enter of new incoming mailinglists,
  16. :History.    v3.1 [hG ] 26 Sep 94 new option 'DebugLevel=DBG/N/K' (default: 5),
  17.                                   changed info message levels, more/better
  18.                                   info messages
  19. :Copyright.  Public Domain
  20. :Language.   ARexx
  21. :Translator. RexxMast
  22. ------------------------------------------------------------------------ */
  23. /*--- ListClient.rexx -----------------------------------------------------
  24.  
  25.     ListClient.rexx V3.0
  26.     ====================
  27.  
  28. ListClient is a tool to sort mails from incoming mailing lists into
  29. local newsgroups (import mode) or sends posting in this newsgroups to
  30. the corresponding mailinglist (export mode).
  31.  
  32. How does it work?
  33. -----------------
  34. IMPORT:
  35.   All incoming mails are scanned for ReplyAddr matching "Mailinglist
  36.   '#?'" (case insensitive). The mails are put into the newsgroup
  37.   mailinglist.#?, where #? is substituted by the #? of the above
  38.   pattern. Further, the mailinglists name and address are added to
  39.   the config variable, if not already present.
  40.  
  41. EXPORT:
  42.   All newsgroups found in the config varibale are scanned for new
  43.   postings. This were forwarded to the corresponding mailinglist by
  44.   sending it to the address found in the config variable.
  45.  
  46.  
  47. For using ListClient, it's quite usefull to have an extra user who
  48. gets all the mailinglists. This user must have the following
  49. configuration variables (V11 style):
  50.     ( READACCESS "#?" )
  51.     ( WRITEACCESS "mailinglist.#?" )
  52.     ( IMPORT "#?" )
  53. For security reasons, set
  54.     ( EXPORT "~(#?)" )
  55. and restrict NETACCESS as far as possible (if at all).
  56.  
  57.  
  58. Usage:
  59. -----
  60.  
  61. Template: Name,Password,Server/K,Export/S,DebugLevel=DBG/N/K
  62.  
  63. Name
  64. Password
  65. Server
  66.   UMS standard command line options
  67.   (defaults to "Lists", "", ""; changeable at top of script)
  68.  
  69. Export
  70.   Export posting to newsgroups. If this switch is not set, ListClient
  71.   will try to move mails to newsgroups.
  72.  
  73. DebugLevel=DBG
  74.   messages with log level lower or equal this value are not only
  75.   written to the UMS Logfile, but also to StdIO.
  76.   (default: 5; changeable at top of script)
  77.  
  78.  
  79. Installation:
  80. -------------
  81.  
  82. For using ListClient, it's quite usefull to have an extra user who
  83. gets all the mailinglists. This user must have the following
  84. configuration variables (V11 style):
  85.     ( READACCESS "#?" )
  86.     ( WRITEACCESS "mailinglist.#?" )
  87.     ( IMPORT "#?" )
  88. For security reasons, set
  89.     ( EXPORT "~(#?)" )
  90. and restrict NETACCESS as far as possible (if at all).
  91.  
  92. If you use an already existing user, make sure, his/her config
  93. matches the above. But beware: is may be a security leak. I porpose
  94. the use of an extra user for thus deamon stuff handling.
  95.  
  96. Further configuration is not nesseccary! ListClient will enter all
  97. incoming mailinglist into it's config variable.
  98.  
  99. For the case you got some postings to be exported to mailinglists not
  100. already present in the config variable, this is the format :-)
  101.     ( ListClient.Mailinglists
  102.         "Ums-Dev , Ums-Dev@umshq.dfv.rwth-aachen.de\n"
  103.         "oberon-a , oberon-a@wossname.apana.org.au\n"
  104.         "AMOK , AMOK@amokle.stgt.sub.org" )
  105.  
  106.  
  107. Advanced Features:
  108. ------------------
  109.  
  110. Okay, for guys willing to but some fingers into the ARexx script,
  111. here where some hints.
  112.  
  113. - Default login options are set at the top of the script.
  114. - The prefix for newsgroups is defined in 'GroupPrefix'
  115. - The config variables name is ProgramName || ".Mailinglists"
  116.  
  117.  
  118. -------------------------------------------------------------------------*/
  119.  
  120. ProgramName = "ListClient";
  121. ArgsTemplate = "Name,Password,Server/K,Export/S,DebugLevel/N/K"
  122.  
  123. /* set default options */
  124. Name = "Lists"
  125. Password = "";
  126. Export = 0;
  127. DebugLevel = 5;
  128.  
  129. GroupPrefix = "mailinglist."
  130.  
  131. /*** Startup ***/
  132.  
  133. call addlib("hgrexxsupport.library",0,-30);
  134. interpret include("REXX:ums/UMSInitStem.rexx")
  135. if rc ~= 0 then do
  136.   say "cannot read UMS include-file!"
  137.   exit 20
  138. end
  139.  
  140. /*** Login ***/
  141.  
  142. account = UMSLogin(name, password, server)
  143. if account = 0 then do
  144.   say "unable to login."
  145.   exit
  146. end
  147.  
  148. /*** Magic ***/
  149.  
  150. FLAGS.01 = MakeFlags(0,1)
  151. FLAGS.012 = MakeFlags(0,1,2)
  152. Mailinglists = ReadUMSConfig(account,ProgramName || ".Mailinglists");
  153.  
  154. IF ~ Export then
  155.   call Import()
  156. else do
  157.   trace ?
  158.   if Mailinglists = '' then do
  159.     log(4,ProgramName || ": nothing to export, no mailinglists defined")
  160.   end; else
  161.     do forever
  162.       parse var Mailinglists ListName "," ListAddr '0A'x Mailinglists
  163.       ListName = strip(ListName); ListAddr = strip(ListAddr)
  164.       if ListName = '' then leave;
  165.       call Export ListName ListAddr
  166.     end
  167. end;
  168.  
  169. /*** Final cleanup ***/
  170.  
  171. BREAK_C:
  172. BREAK_D:
  173. BREAK_E:
  174. BREAK_F:
  175. ERROR:
  176. HALT:
  177. IOERR:
  178. SYNTAX:
  179.  
  180. IF RC ~= 0 THEN DO
  181.   SAY "Error: " rc errortext(rc) "Line" sigl
  182. END
  183.  
  184. /*** Logout ***/
  185.  
  186. if account ~= 0 then do
  187.   call UMSLogout(account)
  188.   account = 0
  189. end
  190.  
  191. exit
  192.  
  193. /*** Check for new messages from the server ***/
  194.  
  195. Import: PROCEDURE expose account GroupPrefix TRUE FLAGS.,
  196.                          UMSUSTAT. UMSCODE_Group UMSCODE_FromName UMSCODE_ToName,
  197.                          UMSCODE_ToAddr UMSCODE_ReplyName UMSCODE_ReplyAddr,
  198.                          UMSCODE_MsgID UMSCODE_Attributes UMSCODE_RefID,
  199.                          Mailinglists Name ProgramName Name UMSNUMFIELDS
  200.  
  201.   say "Moving messages from all lists into groups..."
  202.  
  203.   match = MakeFlags(UMSUSTAT.ReadAccess)
  204.   mask  = MakeFlags(UMSUSTAT.ReadAccess, UMSUSTAT.Old)
  205.  
  206.   call UMSSelectField(account, "L", MakeFlags(0), MakeFlags(),,, UMSCODE_Group, "", true)
  207.   call UMSSelectFlags(account, "L", MakeFlags(1), MakeFlags(),,, "U", mask, match)
  208.  
  209.   last = 0; numMsgs = 0;
  210.   do forever
  211.     last = UMSSearchFlags(account, "L", FLAGS.01, FLAGS.01, last)
  212.     if last = 0 then leave
  213.  
  214.     if ReadUMSMsgField(account,last,msg.,UMSCODE_ReplyName,true) then do
  215.       parse var msg.UMSCODE_ReplyName test "'" listname "'"
  216.       if (upper(test) = "MAILINGLIST ") & (listname ~= "") then do
  217.  
  218.         if ~ReadUMSMsgAll(account, last, msg., true) then do
  219.           call CheckErr
  220.         end
  221.  
  222.         /*** check ref-IDs ***/
  223.         if ReadUMSMsgInfo(account, last, msg.) & (msg.up ~= 0) then do
  224.           drop repmsg.
  225.           if ReadUMSMsgField(account, msg.up, repmsg., UMSCODE_Attributes) then do
  226.             parse var repmsg.UMSCODE_Attributes "oid<" mailref ">"
  227.             msg.UMSCODE_RefID = mailref
  228.           end
  229.         end
  230.  
  231.         /* insert into config var, if not already there */
  232.         call CheckEntry(listname,msg.UMSCODE_ReplyAddr)
  233.  
  234.         call UMSSelectMsg(account,"U", MakeFlags(UMSUSTAT.Old), MakeFlags(), last)
  235.  
  236.         msg.UMSCODE_Group = GroupPrefix || listname
  237.         msg.UMSCODE_Attributes = "oid<" || msg.UMSCODE_MsgID || "> "
  238.         drop msg.UMSCODE_MsgID msg.UMSCODE_ToName msg.UMSCODE_ToAddr
  239.         drop msg.UMSCODE_ReplyName msg.UMSCODE_ReplyAddr msg.UMSCODE_Folder
  240.  
  241.         num = WriteUMSMsg(account, msg.)
  242.         /*say num*/
  243.         if num = 0 then do
  244.           call CheckErr
  245.         end; else do
  246.           numMsgs = numMsgs + 1;
  247.           call log(7,"forwarded message written by '" || msg.UMSCODE_FromName ||,
  248.                      "' to '" || msg.UMSCODE_Group || "'")
  249.         end
  250.  
  251.         drop msg.
  252.       end;
  253.     end
  254.   end
  255.   call log(5,"imported" numMsgs "messages");
  256. return
  257.  
  258. /*** Check for new messages from the users ***/
  259.  
  260. Export: PROCEDURE Expose account GroupPrefix TRUE FLAGS.,
  261.                          UMSUSTAT. UMSCODE_Group UMSCODE_FromName UMSCODE_FromAddr,
  262.                          UMSCODE_ToName UMSCODE_ToAddr UMSCODE_ReplyName,
  263.                          UMSCODE_ReplyAddr UMSCODE_MsgID UMSCODE_Attributes,
  264.                          UMSCODE_RefID UMSNUMFIELDS
  265.  
  266.   parse arg listname listaddr .
  267.  
  268.   groupname = GroupPrefix || listname
  269.   match = MakeFlags(UMSUSTAT.ReadAccess)
  270.   mask  = MakeFlags(UMSUSTAT.ReadAccess, UMSUSTAT.Old)
  271.  
  272.   call UMSSelectField(account, "L", MakeFlags(0), MakeFlags(),,, UMSCODE_Group, groupname, true)
  273.   call UMSSelectField(account, "L", MakeFlags(1), MakeFlags(),,, UMSCODE_FromAddr, "", true)
  274.   call UMSSelectFlags(account, "L", MakeFlags(2), MakeFlags(),,, "USER", mask, match)
  275.  
  276.   last = 0; numMsgs = 0;
  277.   do forever
  278.     last = UMSSearchFlags(account, "L", FLAGS.012, FLAGS.012, last)
  279.     if last = 0 then leave
  280.     if ~ReadUMSMsgAll(account, last, msg.) then do
  281.       call CheckErr
  282.     end
  283.  
  284.     /*** check ref-IDs ***/
  285.     if ReadUMSMsgInfo(account, last, msg.) & (msg.up ~= 0) then do
  286.       drop repmsg.
  287.       if ReadUMSMsgField(account, msg.up, repmsg., UMSCODE_Attributes) then do
  288.         parse var repmsg.UMSCODE_Attributes "oid<" mailref ">"
  289.         msg.UMSCODE_RefID = mailref
  290.       end
  291.     end
  292.  
  293.     drop msg.UMSCODE_Group
  294.  
  295.     msg.UMSCODE_ToName = "Mailinglist '" || listname || "'"
  296.     if listaddr ~= "" then
  297.       msg.UMSCODE_ToAddr = listaddr
  298.     else
  299.       drop msg.UMSCODE_ToAddr
  300.  
  301.     msg.UMSCODE_Attributes = "oid<" || msg.UMSCODE_MsgID || "> "
  302.     drop msg.UMSCODE_MsgID
  303.  
  304.     num = WriteUMSMsg(account, msg.)
  305.     say num
  306.     if num = 0 then do
  307.       call CheckErr
  308.     end; else do
  309.       numMsgs = numMsgs + 1;
  310.       call log(7,"forwarded message written by '" || msg.UMSCODE_FromName ||,
  311.                  "' from '" || groupname || "'")
  312.     end
  313.  
  314.     drop msg.
  315.   end
  316.   call log(5,"exported" numMsgs "messages to list '" || listname || "'),
  317. return
  318.  
  319. /*** check if mailinglist is in our list ***/
  320.  
  321. CheckEntry:
  322.   listname=arg(1); addr=arg(2);
  323.  
  324.   ml = Mailinglists
  325.   do forever
  326.     parse var ml LName "," LAddr '0A'x ml
  327.     LName = strip(LName); LAddr = strip(LAddr)
  328.     if upper(LName) = upper(listname) then do
  329.        /* todo? update address */
  330.       return FALSE
  331.     end; else if ml = '' then do
  332.       if Mailinglists = '' then
  333.         Mailinglists = listname "," addr
  334.       else
  335.         Mailinglists = Mailinglists || '0A'x || listname "," addr
  336.       if ~ WriteUMSConfig(account, ProgramName || ".Mailinglists", Mailinglists, Name) then
  337.         call CheckErr()
  338.       return TRUE
  339.     end
  340.   end
  341.  
  342. /*** Show a message for debugging ***/
  343.  
  344. ShowMsg:
  345.   do field = 0 to UMSNUMFIELDS
  346.     if (symbol("msg." || field) = "VAR") & (field ~= UMSCODE_MsgText) & (field ~= UMSCODE_Comments) then do
  347.       say "Field #" || field || ": '" || msg.field || "'"
  348.     end
  349.   end
  350. return
  351.  
  352. /*** Support ***/
  353.  
  354. log: PROCEDURE expose account debugLevel
  355.   level=arg(1); text=arg(2)
  356.   if level <= debugLevel then say text
  357.   call LogUMS(account, level, text)
  358. return 0
  359.  
  360. CheckErr: PROCEDURE expose account
  361.   err = UMSErrNum(account)
  362.   if err ~= 0 then do
  363.     log (3,"UMS Error #" || err || ": " || UMSErrTxt(account))
  364.   end return
  365.